package com.wenqiner.requesttool.core.business.lingyin;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson2.JSONObject;
import com.wenqiner.requesttool.core.exception.CustomException;
import com.wenqiner.requesttool.util.AESEncryptUtil;
import com.wenqiner.requesttool.util.CommonUtil;
import com.wenqiner.requesttool.util.DigitalSignatureUtil;
import com.wenqiner.requesttool.util.RSAUtil;

import java.nio.charset.StandardCharsets;

/**
 * @author rhf
 * @date 2023-03-01
 **/
public class LingyinDataProcess {

    /**
     * 内部请求加密
     *
     * @param requestData  请求参数
     * @param publicKeyStr 公钥base64
     * @return java.lang.String
     * @author rhf
     */
    public static String innerEncoder(String requestData, String publicKeyStr) throws Exception {
        ParamData<?> paramData = new ParamData<>();
        String randomString = RandomUtil.randomString(16);
        String code = RSAUtil.encryptByPublicKey(publicKeyStr, randomString);
        String data = AESEncryptUtil.encryptBase64(requestData, randomString);
        paramData.setEncryptedData(data);
        paramData.setSecretCode(code);
        return JSONObject.toJSONString(paramData);
    }

    /**
     * 内部请求解密
     *
     * @param responseData 响应报文
     * @param publicKeyStr 公钥base64
     * @return java.lang.String
     * @author rhf
     */
    public static String innerDecoder(String responseData, String publicKeyStr) throws Exception {
        ParamData<?> paramData = JSONObject.parseObject(responseData, ParamData.class);
        //用平台私钥解密aes
        String aesKey = RSAUtil.decryptByPublicKey(publicKeyStr, paramData.getSecretCode());
        //解密数据
        String s = AESEncryptUtil.decryptBase64(paramData.getEncryptedData(), aesKey);
        ParamData<String> data = new ParamData<>();
        data.setResponseCode(paramData.getResponseCode());
        data.setData(s);
        return CommonUtil.formatJson(data);
    }

    /**
     * @param requestData      请求报文
     * @param merPrivateKeyStr 商户私钥
     * @param publicKeyStr     平台公钥
     * @param timestamp        时间戳
     * @return java.lang.String
     * @author rhf
     */
    public static String outerEncoder(String requestData, String merPrivateKeyStr, String publicKeyStr, String timestamp) throws Exception {
        ParamData<?> paramData = new ParamData<>();
        String randomString = RandomUtil.randomString(16);
        String code = RSAUtil.encryptByPublicKey(publicKeyStr, randomString);
        String data = AESEncryptUtil.encryptBase64(requestData, randomString);
        String sign = DigitalSignatureUtil.createSign(requestData, merPrivateKeyStr, null != requestData ? "&time=" + timestamp : "time=" + timestamp);

        paramData.setEncryptedData(data);
        paramData.setSecretCode(code);
        paramData.setSign(sign);
        return JSONObject.toJSONString(paramData);
    }

    /**
     * @param responseData     响应报文
     * @param merPrivateKeyStr 商户私钥
     * @param publicKeyStr     平台公钥
     * @param timestamp        时间戳
     * @return java.lang.String
     * @author rhf
     */
    public static String outerDecoder(String responseData, String merPrivateKeyStr, String publicKeyStr, String timestamp) throws Exception {
        ParamData<?> paramData = JSONObject.parseObject(responseData, ParamData.class);
        //用平台私钥解密aes
        String aesKey = RSAUtil.decryptByPublicKey(publicKeyStr, paramData.getSecretCode());
        //解密数据
        String resData = AESEncryptUtil.decryptBase64(paramData.getEncryptedData(), aesKey);
        //验签
        String s = DigitalSignatureUtil.ascSort(resData);
        if (s != null) {
            s = String.join("",s, "&time=" ,timestamp);
        } else {
            s = String.join("","time=" ,timestamp);
        }
        boolean verifyFlag = RSAUtil.verifySign(s.getBytes(StandardCharsets.UTF_8),
                publicKeyStr, paramData.getSign());
        if (!verifyFlag) {
            throw new CustomException("验签失败!");
        }
        ParamData<String> data = new ParamData<>();
        data.setResponseCode(paramData.getResponseCode());
        data.setData(resData);
        return CommonUtil.formatJson(data);
    }
}
